//
//  YbrDLNAUtil.m
//  wifibox
//
//  Created by os X 10.9 on 15-1-12.
//  Copyright (c) 2015年 yinbaner. All rights reserved.
//  这个就是dlna通信的方式


#define scanTimeSpace       2               // 2s - 快速扫描的时候的时间间隔
#define scanSlowTimeSpace   8               // 6s - 慢速扫描的时间间隔 (假如已经连接上了,或者已经搜索到相应的device了)
#define noScanRemoveNum     30              // 扫描了三次假如都没有这个设备的话,可以认为这个设备已被移除了
#define DefaultLifeCount    6               // 默认生命值为6
#define DefaultNotRecieveDeviceCount  15    // 默认没有收到device的次数

#import "YbrDLNAUtil.h"
#import "YbrDevice.h"
#import "YbrSetUpWifiBoxUtil.h"
#import "GCDAsyncUdpSocket.h"
#import "YbrDlnaPlayer.h"
#import "YbrDeviceList.h"
#import "YbrSystemUtil.h"
#import "YbrPlayer.h"
#import <MediaPlayer/MediaPlayer.h>
//#import "YbrDeviceDao.h"
#import <ifaddrs.h>
#import <arpa/inet.h>
#import "YbrFileUtils.h"
#import "YbrJsonUtil.h"
#import "YbrMusicPlayUtil.h"
#import "YbrPerferenceTool.h"
#import "AppDelegate.h"


@interface YbrDLNAUtil () <GCDAsyncUdpSocketDelegate>
{
    long tag;
}
@property (nonatomic, strong)   NSMutableArray      * deviceList;               // 设备的列表
@property (nonatomic, strong)   YbrDevice           * chooseDevice;             // 选择的设备
@property (nonatomic, strong)   GCDAsyncUdpSocket   * socket;
@property (nonatomic)           BOOL                isSlow;                     // 是慢速状态吗
@property (nonatomic)           int                 scanNum;                    // 现在已经扫描多少遍了
@property (nonatomic, strong)   NSTimer             * myTimer;
@property (nonatomic)           BOOL                flag;                       // 是否要扫描设备
@property (nonatomic)           NSString            * currentPhoneIp;           // 当前手机设备的IP
@property (nonatomic)           int                 currentReachabilityStatus;  // 当前的网络状态
@property (nonatomic)           int                 receiveDeviceCount;         // 接收设备的次数
@property (nonatomic)           BOOL                isStopScanDevice;           // 是否已停止搜索设备
@end


static YbrDLNAUtil * dlnaUtil;


@implementation YbrDLNAUtil


// step1
// 如果想实现单例模式,重写此方法
// 该方法线程安全
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t oncePredicate;   // 此对象存在多线程中,
    
    // 这里的静态代码快只执行一次
    dispatch_once(&oncePredicate, ^{
        dlnaUtil            =  [super allocWithZone:zone];
        
        dlnaUtil.socket     =   [[GCDAsyncUdpSocket alloc] initWithDelegate:dlnaUtil delegateQueue:dispatch_get_main_queue()];
        NSError *error      =   nil;
        [dlnaUtil.socket bindToPort:7967 error:nil];
        [dlnaUtil.socket enableBroadcast:YES error:&error];
        [dlnaUtil.socket joinMulticastGroup:@"224.0.0.1" error:&error];
        [dlnaUtil.socket beginReceiving:&error];
        
        dlnaUtil.flag           =   YES;
        dlnaUtil.isSlow         =   NO;
        dlnaUtil.chooseDevice   =   nil;
        dlnaUtil.receiveDeviceCount      =   4;
        dlnaUtil.isStopScanDevice       = NO;
        dlnaUtil.currentPhoneIp =   [YbrSystemUtil getDeviceCurrentIpAddress];
        // 初始化设备列表
        if(dlnaUtil.deviceList == nil) {
            dlnaUtil.deviceList             =   [NSMutableArray array];
        }
        
        dlnaUtil.currentReachabilityStatus  =   -1;
    });
    return dlnaUtil;
}


+(YbrDLNAUtil *) getInstance
{
    return [[self alloc] init];
}


// 获取当前的网络状态
-(int) getCurrentReachability
{
    return self.currentReachabilityStatus;
}


// 移除所有的设备,包括已经连接上的设备
-(void) clear
{
    [self.deviceList removeAllObjects];
    [self setSelectedDevice:nil];
    // 出了这个还需要处理什么？
    
}


// 移除掉当前无关的设备,若手机连接的WiFi是 EBER_******, 则移除其他设备
-(void) clearOtherDevice
{
    NSString * currentWifiName = [YbrSystemUtil currentWifiSSID];
    
    // 若手机连接的WiFi为空
    if (currentWifiName == nil || [currentWifiName isKindOfClass:[NSNull class]] || [currentWifiName isEqualToString:@""]) {
        [self clear];
    }
    // 判断连接的WiFi是不是含有 EBER
    else if([currentWifiName rangeOfString:@"EBER"].location != NSNotFound)
    {
        if(![_chooseDevice.DeviceName isEqualToString:currentWifiName])
        {
            _chooseDevice       =   nil;
            [self postDlnaDeviceChangeNotification];
        }
        
        if (_deviceList != nil && _deviceList.count != 0)
        {
            for (YbrDevice * mDevice in _deviceList)
            {
                if (![mDevice.DeviceName isEqualToString:currentWifiName])
                {
                    [_deviceList removeObject:mDevice];
                    [self postDlnaDeviceChangeNotification];
                }
            }
        }
    }
    else{
        // add code here
    }
}


// 移除指定设备
-(void)clearByDevice:(NSString *) deviceName
{
    if (deviceName == nil)
    {
        return;
    }
    
    if ([deviceName isKindOfClass:[NSNull class]] || [deviceName isEqualToString:@""])
    {
        return;
    }
    
    if (self.deviceList == nil || self.deviceList.count == 0)
    {
        return;
    }
    
    NSLog(@"---------设备列表-------%@",self.deviceList);
    
    for (YbrDevice * device in self.deviceList)
    {
        if ([device.DeviceName isEqualToString:deviceName])
        {
            [_deviceList removeObject:device];
        }
    }
}


// 获取已连接设备
-(YbrDevice *) getSelectedDevice
{
    return self.chooseDevice;
}


// 这里可以为
// 设置连接的设备
-(void) setSelectedDevice:(YbrDevice *) device
{
    // 删除定时列表和非定时列表
    [YbrFileUtils deleFile:TimeBoxPath];
    [YbrFileUtils deleFile:NoTimerPath];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:PlayListChange object:nil];
    
    if(device != nil)
    {
        if ([device.DeviceIpAddr isKindOfClass:[NSNull class]] || [device.DeviceIpAddr rangeOfString:@"0.0.0."].location != NSNotFound ||
            [device.DeviceIpAddr isEqualToString:@""])
        {
            [self clearByDevice:device.DeviceName];
            return;
        }
        else
        {
            self.chooseDevice               =   device;
            self.chooseDevice.isSelected    =   YES;
            [YbrMusicPlayUtil playOnDlna];
            for (int i = 0; i < _deviceList.count; i ++) {
                YbrDevice *obj = _deviceList[i];
                if ([obj.DeviceName isEqualToString:device.DeviceName])
                {
                    obj.isSelected          =   YES;
                    [_deviceList setObject:obj atIndexedSubscript:i];
                }
            }
            [[YbrPerferenceTool prefer] setSeleDeviceToPre:[YbrJsonUtil getJson:self.chooseDevice]];
        }
        
    }
    else
    {
        self.chooseDevice   =   nil;
        [YbrMusicPlayUtil StopDlnaGetInfo];
        [[NSNotificationCenter defaultCenter] postNotificationName:DLNADeviceChange object:nil];
    }
    
    [[NSNotificationCenter defaultCenter] postNotificationName:DLNADeviceSeleChange object:nil];
}


// 通过设备名称设置当前连接设备
-(void) setSelectedDeviceByName:(NSString *) deviceName
{
    if ([deviceName isKindOfClass:[NSNull class]] || [deviceName isEqualToString:@""] )
    {
        return;
    }
    
    for (YbrDevice *device in self.deviceList)
    {
        if([device.DeviceName isEqualToString:deviceName])
        {
            [self setSelectedDevice:device];
            return;
        }
    }
}


// 更新手机IP,并通知前台修改httpserver服务器
-(void) updatePhoneIp
{
    // 获取本地服务器url
    _currentPhoneIp             =   [YbrSystemUtil getDeviceCurrentIpAddress];
    NSString * service_url      =   [[YbrPerferenceTool prefer] getHttpServiceUri];
    
    if(![_currentPhoneIp isEqualToString:@"0.0.0.0"] && _currentPhoneIp != nil){
        if([service_url rangeOfString:_currentPhoneIp].location == 	NSNotFound){
            [[NSNotificationCenter defaultCenter] postNotificationName:PhoneIpChangedNotication object:_currentPhoneIp];
        }
    }
}


// 扫描设备,将移除设备的方法去掉,同名设备取代新IP,检查手机ip是否发生改变
-(void) scanDevice {
    [self updatePhoneIp];
    
    if(self.myTimer == nil) {
        self.myTimer        =   [NSTimer scheduledTimerWithTimeInterval:dlnaUtil.isSlow ? scanSlowTimeSpace : scanTimeSpace target:self selector:@selector(scanDevice) userInfo:nil repeats:YES];
    }
    
//    [self checkAndRemoveDevice];
    
    NSTimeInterval timeout  =   5000;
    UInt16 port             =   7967;    
    NSString *request       =   @"{\"Req\":\"ScanDevice\"}";
    NSData *data            =   [NSData dataWithData:[request dataUsingEncoding:NSASCIIStringEncoding]];
    tag ++;
    [self.socket sendData:data toHost:@"255.255.255.255" port:port withTimeout:-1 tag:tag];
    [self.socket beginReceiving:nil];
    self.scanNum ++;
    // 当数量超过一个的时候
    [self setSlowOrFirstScan:self.deviceList.count >= 1];
}


// 获取设备列表
-(NSMutableArray *) getDevices
{
    return self.deviceList;
}


// 根据device的信息进行更改相应的内容
-(void) getDeviceInfo:(NSString *) content
{
    NSData *jsonData            =   [content dataUsingEncoding:NSUTF8StringEncoding];
    id object                   =   [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
    
    if([YbrSetUpWifiBoxUtil isOK:object])
    {
        NSData *jsonData        =   [content dataUsingEncoding:NSUTF8StringEncoding];
        id object               =   [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
        id mydevice             =   object[@"Body"];
        
        // 设备合法性拦截
        NSString *deviceName    =   mydevice[@"DeviceName"];
        NSString * deviceIp     =   mydevice[@"DeviceIpAddr"];
        if(deviceName == nil || deviceName.length == 0)
        {
            if (self.isStopScanDevice)
            {
                return;
            }
            return;
        }
        
        if ([deviceIp isEqualToString:@"0.0.0.0"] || [deviceIp isEqualToString:@""])
        {
            return;
        }
        
        if(![self isHaveDev:deviceName]) {
            [self addDevice:mydevice];
        }else{
            // 如果设备名称一样,则替换IP
            [self updateDevice:mydevice];
        }
        
        self.receiveDeviceCount = (self.receiveDeviceCount >= DefaultNotRecieveDeviceCount * 2) ? DefaultNotRecieveDeviceCount :  (self.receiveDeviceCount + 5);
        
    }
}


// 检测设备是否过期,如果过期将其移除
-(void) checkAndRemoveDevice {
    if(self.deviceList == nil) {
        return;
    }
    
    
    if(self.deviceList == nil || self.deviceList.count == 0) {
        // 发送通知
        [[NSNotificationCenter defaultCenter] postNotificationName:DLNADeviceChange object:nil];
    }
}


// 添加设备
-(void) addDevice:(id) mydevice
{
    if(self.deviceList == nil)
    {
        self.deviceList             =   [NSMutableArray array];
    }
    
    YbrDevice *device               =   [[YbrDevice alloc] init];
    
    // 判断是否为null
    if ([mydevice[@"DeviceIpAddr"] isKindOfClass:[NSNull class]])
    {
        return;
    }
    
    // 能否找到0.0.0.
    if ([mydevice[@"DeviceIpAddr"] rangeOfString:@"0.0.0."].location != NSNotFound)
    {
        return;
    }
    
    if (![mydevice[@"DeviceIpAddr"] isEqualToString:@"0.0.0.0"] && mydevice[@"DeviceIpAddr"] != nil && ![mydevice[@"DeviceIpAddr"] isEqualToString:@""])
    {
        device.DeviceName               =   mydevice[@"DeviceName"];
        device.DeviceIpAddr             =   mydevice[@"DeviceIpAddr"];
        device.DeviceFiremwareVersion   =   mydevice[@"DeviceFiremwareVersion"];
        device.HttpApiPort              =   mydevice[@"HttpApiPort"];
        device.lifeCount                =   DefaultLifeCount;
        device.addTime                  =   [[NSDate date] timeIntervalSinceReferenceDate];
        
        
//        [device getDeviceInfo];//获取设备的相关设置
        [self.deviceList addObject:device];
        [self postDlnaDeviceChangeNotification];// 发送设备改变通知
    }
    
    // 自动连接设备
//    NSString * oldDeviceName            =   [[AppDelegate app].perfer getSeleDeviceIP];
    
    if (_deviceList.count == 1)
    {
        [self connectDevice:_deviceList[0]];
    }
    else
    {
        for (int i = 0; i < _deviceList.count; i ++)
        {
            YbrDevice *tempObj = _deviceList[i];
//            if ([tempObj.DeviceName isEqualToString:oldDeviceName])
//            {
//                [self connectDevice:tempObj];
//                break;
//            }
        }
    }
}


// 拦截设备
-(void)connectDevice:(YbrDevice *)device
{
    if ([YbrMusicPlayUtil isDlnaState] == NO)
    {
        [YbrMusicPlayUtil Stop];
    }
    [[YbrDLNAUtil getInstance] setSelectedDevice:device];
    [YbrMusicPlayUtil startDlnaGetInfo];
}


// 发送设备改变了的通知
-(void) postDlnaDeviceChangeNotification
{
    [[NSNotificationCenter defaultCenter] postNotificationName:DLNADeviceChange object:nil];
}


// 更新设备音量
-(void)updateDeviceVolume:(int)volume
{
    
    NSLog(@"----更新设备音量------------%d",volume);
    
    
    // 更新正在播放的设备
    if(_chooseDevice != nil)
    {
        _chooseDevice.currentVolume = volume;
        
        if (_deviceList == nil || _deviceList.count == 0)
        {
            return;
        }
        for (int i = 0; i < _deviceList.count; i ++)
        {
            YbrDevice *tempDevice = _deviceList[i];
            if ([tempDevice.DeviceName isEqualToString:_chooseDevice.DeviceName])
            {
                tempDevice.currentVolume = volume;
                [self postDlnaDeviceChangeNotification];
            }
        }
    }
}


// 更新设备的IP
-(void) updateDevice:(id) device
{
    if(self.deviceList == nil || device)
    {
        return;
    }
    
    // 更新正在播放的设备
    if(_chooseDevice != nil)
    {
        if([_chooseDevice.DeviceName isEqualToString:device[@"DeviceName"]])
        {
            if(![device[@"DeviceIpAddr"] isEqualToString:_chooseDevice.DeviceIpAddr])
            {
                _chooseDevice.DeviceIpAddr                      =   device[@"DeviceIpAddr"];
                [YbrMusicPlayUtil startDlnaGetInfo];
            }
        }
    }
    
    // 更新设备列表
    for (int i = 0; i < self.deviceList.count; i ++)
    {
        YbrDevice *tempDevice = self.deviceList[i];
        if ([tempDevice.DeviceName isEqualToString:device[@"DeviceName"]])
        {
            if (![device[@"DeviceIpAddr"] isEqualToString:tempDevice.DeviceIpAddr])
            {
                tempDevice.DeviceIpAddr     =   device[@"DeviceIpAddr"];
                [self postDlnaDeviceChangeNotification]; // 通知界面改变设备的IP
            }
            tempDevice.addTime              =   [[NSDate date] timeIntervalSinceReferenceDate];
            return;
        }
    }
}


// 判断搜索的设备中是否含有该设备
-(BOOL) isHaveDev:(NSString *) deviceName
{
    if(self.deviceList == nil)
    {
        return NO;
    }
    
    for (int i = 0; i < self.deviceList.count; i ++)
    {
        YbrDevice *tempDevice = self.deviceList[i];
        if([tempDevice.DeviceName isEqualToString:deviceName])
        {
            return YES;
        }
    }
    return NO;
}


// 设置成快速的
-(void) setFastScan
{
    [self.myTimer invalidate];
    self.myTimer    =   nil;
    self.isSlow     =   NO;
    self.isStopScanDevice = NO;
    self.scanNum    =   0;
    self.myTimer    =   [NSTimer scheduledTimerWithTimeInterval:self.isSlow ? scanSlowTimeSpace : scanTimeSpace target:self selector:@selector(scanDevice) userInfo:nil repeats:YES];
}


// 设置扫描设备的速度变慢
-(void) setSlowOrFirstScan:(BOOL) flag
{
    if(self.isSlow != flag)
    {
        self.isSlow         =   flag;
        [self.myTimer invalidate];
        self.myTimer        =   nil;
        
        if(!self.isSlow)
        {
            self.scanNum    =   0;
        }
        
        // 因为改变了之后可能会导致之前的addTime很大或者很小
        long nowTime = [[NSDate date] timeIntervalSinceReferenceDate];
        if(self.deviceList != nil)
        {
            for (int i = 0; i < self.deviceList.count; i ++)
            {
                ((YbrDevice *)self.deviceList[i]).addTime = nowTime;
            }
        }
        
        self.myTimer        =   [NSTimer scheduledTimerWithTimeInterval:self.isSlow ? scanSlowTimeSpace : scanTimeSpace target:self selector:@selector(scanDevice) userInfo:nil repeats:YES];
    }
}


// 停止扫描设备
-(void) stopScan
{
    [self.myTimer invalidate];
    self.myTimer            =   nil;
    self.isStopScanDevice   =   YES;
}


// 获取设备的http访问连接
-(NSString *) getDeviceReqHttpUrl
{
    if(self.chooseDevice != nil)
    {
        return [NSString stringWithFormat:@"http://%@/httpapi.html" ,self.chooseDevice.DeviceIpAddr];
    }
    return nil;
}


// 获取制定设备的http访问连接
-(NSString *) getDeviceReqHttpUrlByDevice:(YbrDevice *)device
{
    if(device != nil)
    {
        return [NSString stringWithFormat:@"http://%@/httpapi.html" ,device.DeviceIpAddr];
    }
    return nil;
}


// 判断是否为dlna状态
-(BOOL) isDLNAState
{
    if(self.chooseDevice == nil)
    {
        return NO;
    }
    return YES;
}


// 广播后,周围设备的反馈
#pragma mark socket通信的反馈
// 发现有连接,打印连接信息
-(void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address
{
    NSLog(@"Message didConnectToAddress %@",[[NSString alloc]initWithData:address encoding:NSUTF8StringEncoding]);
}


// 连接有错误,打印连接错误信息
-(void)udpSocket:(GCDAsyncUdpSocket *)sock didNotConnect:(NSError *)error
{
    NSLog(@"Message didNotConnect %@",error);
}


// 周围设备接收到广播,反馈信息回来,若信息没有返回,打印没有接收信息
-(void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error
{
    
}


// 接受到这些信息
// 获取设备的相关信息
-(void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext
{
    NSString *result    =   [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    [self getDeviceInfo:result];
}


-(void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag
{
    //NSLog(@"Message didSendDataWithTag");
}


// 广播异常退出,打印异常退出信息
-(void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error
{
    if([dlnaUtil.socket isClosed]){
        dlnaUtil.socket     =   [[GCDAsyncUdpSocket alloc] initWithDelegate:dlnaUtil delegateQueue:dispatch_get_main_queue()];
        NSError *error      =   nil;
        [dlnaUtil.socket bindToPort:7967 error:nil];
        [dlnaUtil.socket enableBroadcast:YES error:&error];
        [dlnaUtil.socket joinMulticastGroup:@"224.0.0.3" error:&error];
        [dlnaUtil.socket beginReceiving:&error];
        
    }
    else
    {
        
    }
}
@end
